#! /usr/bin/env python

import sys
import os
import shutil
import optparse
import imp
import commands

def execute_and_return(cmd):
    o = commands.getstatusoutput(cmd)
    return o[0]

def execute(cmd):
    err = execute_and_return(cmd)
    if err != 0:
        print "Failed to execute cmd [%s], errno = [%d]" % (cmd, err)
        sys.exit(err)

    return err

def load_config(filename):
    f = file(filename, 'rU')
    try:
        m = imp.load_source('', filename, f)
    except SyntaxError, error:
        print error
    f.close()
    execute('rm -f ' + filename + 'c')

    return m

def get_args():
    usage = "usage: %prog [options] COMMAND args"
    
    description = "setup.py an assistant tool for installing distribution.\n"\
            + "\n  The most commonly used commands are:\n"\
            + "  install               full install or install some of the components included\n"\
            + "                        in the distribution package\n"\
            + "  uninstall             uninstall full or uninstall some of the components\n"\
            + "  upgrade               install the newest versions of the components \n"\
            + "                        included in the distribution package\n"\
            + "  check                 dependencies check on the target host.\n"\
            + "\n  Args are:\n"\
            + "  full                  install all componets\n"\
            + "  env                   install the runtime environment for executable file\n"\
            + "  bin                   install the executable file\n"\
            + "  conf                  install the configuration files\n"\
            + "  deps                  install the dependency libraries and tools \n"\
            + "                        for running executable file\n"

    optparse.OptionParser.format_description = lambda self, formatter: self.description
    p = optparse.OptionParser(usage = usage,
                version="%prog 0.1.1",
                description = description)
    p.add_option("", "--prefix", help="specify the install path")

    (opt, args) = p.parse_args()

    if len(args) < 1 or len(args) > 2:
        p.error("Have you read the Usage? Try [setup.py --help]!")
        sys.exit(-1)

    if args[0] != 'install' \
       and args[0] != 'uninstall' \
       and args[0] != 'upgrade' \
       and args[0] != 'check':
        p.error("Unsupported command [%s]!? Try [setup.py --help]!" % args[0])
        sys.exit(-1)

    return (opt, args)

def __get_install_root(opt, default_install_root):
    if opt.prefix != None:
        install_root = os.path.abspath(os.path.expanduser(opt.prefix))
    else:
        install_root = os.path.abspath(os.path.expanduser(default_install_root))

    return install_root

def __install_component(install_root, src, dest):
    abs_dest = install_root + '/' + dest
    if not os.path.exists(abs_dest):
        print 'Error: [%s] does not exist!' % abs_dest
        sys.exit (-1)

    curdir = os.getcwd()
    for root, dirs, files in os.walk(curdir + '/' + src):
        #for dir in dirs:
        #    print os.path.join(root, dir)
        for file in files:
            dest_file = os.path.join(root, file)
            if os.path.exists(dest_file):
                print 'Warning: File [%s] has aleady existed, Skip it!' % dest_file
            else:
                execute('cp ' + os.path.join(root, file) + ' ' + abs_dest)

    print 'Install ' + src + ' to [' + abs_dest + '] OK!'

def __install_env():
    ret = execute_and_return('python ' + os.getcwd() + '/scripts/env_gen.py > .env_gen.log')
    if ret != 0:
        print "Error: Enviroment generate Failed, Please open the .env_gen.log for error details!"
        sys.exit(ret)
    print "Enviroment generate OK!"

def do_install(layout, component, opt):
    install_root = __get_install_root(opt, layout.default_install_root)

    if component == 'full':
        __install_env()
        for c in layout.layout:
            __install_component(install_root, c[1], c[2])
    elif component == 'env':
        __install_env()
    else:
        for c in layout.layout:
            if c[0] == component:
                __install_component(install_root, c[1], c[2])

def __uninstall_component(uninstall_root, src, dest):
    abs_dest = uninstall_root + '/' + dest
    if not os.path.exists(abs_dest):
        print 'Warning: [%s] does not exist!' % abs_dest
        print 'Uninstall ' + '[' + abs_dest + '] OK!'
        sys.exit (0)

    curdir = os.getcwd()
    for root, dirs, files in os.walk(curdir + '/' + src):
        #for dir in dirs:
        #    print os.path.join(root, dir)
        for file in files:
            dest_file = abs_dest + '/' + file
            if not os.path.exists(dest_file):
                print 'Warning: File [%s] does not exist, Skip it!' % dest_file
            else:
                execute('rm ' + dest_file)

    print 'Uninstall ' + '[' + abs_dest + '] OK!'

def do_uninstall(layout, component, opt):
    uninstall_root = __get_install_root(opt, layout.default_install_root)

    if component == 'full':
        for c in layout.layout:
            __uninstall_component(uninstall_root, c[1], c[2])
    else:
        for c in layout.layout:
            if c[0] == component:
                __uninstall_component(uninstall_root, c[1], c[2])

def __upgrade_component(upgrade_root, src, dest):
    abs_dest = upgrade_root + '/' + dest
    if not os.path.exists(abs_dest):
        print 'Error: [%s] does not exist!' % abs_dest
        sys.exit (-1)

    curdir = os.getcwd()
    for root, dirs, files in os.walk(curdir + '/' + src):
        #for dir in dirs:
        #    print os.path.join(root, dir)
        for file in files:
            dest_file = os.path.join(root, file)
            if os.path.exists(dest_file):
                execute('rm ' + dest_file)
            else:
                print 'Warning: File [%s] does not exist, we install it!' % dest_file
            execute('cp ' + os.path.join(root, file) + ' ' + abs_dest)

    print 'Upgrade [' + src + '] OK!'

def do_upgrade(layout, component, opt):
    upgrade_root = __get_install_root(opt, layout.default_install_root)

    if component == 'full':
        for c in layout.layout:
            __upgrade_component(upgrade_root, c[1], c[2])
    else:
        for c in layout.layout:
            if c[0] == component:
                __upgrade_component(upgrade_root, c[1], c[2])

def do_check():
    curdir = os.getcwd()
    ret = execute_and_return('python ' + curdir + '/scripts/deps_check.py > .deps_check.log') 
    if ret != 0:
        print "Error: dependencies check Failed! Please open .deps_check.log for details!"
        sys.exit(ret)
    print "Dependencies Check OK!"

def setup_main():
    layout = load_config('layout.cfg')
    opt, args = get_args()

    if len(args) < 2:
        component = 'full'
    else:
        component = args[1]

    if args[0] == 'install':
        do_install(layout, component, opt)
    elif args[0] == 'uninstall':
        do_uninstall(layout, component, opt)
    elif args[0] == 'upgrade':
        do_upgrade(layout, component, opt)
    elif args[0] == 'check':
        do_check()
    
    sys.exit(0)


if __name__ == '__main__':
    setup_main()
